package com.webcamtracker.image.color;

import com.webcamtracker.image.color.gevers.GeversColor;
import com.webcamtracker.image.color.hsi.HSIColor;
import com.webcamtracker.image.color.hsv.HSVColor;
import com.webcamtracker.image.color.rgb.RGBColor;


public class ColorSpaceConversions {
    public static ColorSpaceConverter<HSIColor> hsiConverter;
    public static ColorSpaceConverter<HSVColor> hsvConverter;
    public static ColorSpaceConverter<GeversColor> geversConverter;

    static {
        hsiConverter = new HSIColorSpaceConverter();
        hsvConverter = new HSVColorSpaceConverter();
        geversConverter = new GeversColorSpaceConverter();
    }

    public static RGBColor fromHSVtoRGB(HSVColor color) {
        final int rgb;
        rgb = java.awt.Color.HSBtoRGB((float) color.getHue(), (float) color.getSaturation(), (float) color.getBrightness());
        return new RGBColor(rgb);

    }

    public static HSIColor fromRGBtoHSI(RGBColor rgb) {
        int r = rgb.getRed();
        int g = rgb.getGreen();
        int b = rgb.getBlue();
        return hsiConverter.getColor(r, g, b);
    }

    public static GeversColor fromRGBtoGevers(RGBColor rgb) {

        int r = rgb.getRed();
        int g = rgb.getGreen();
        int b = rgb.getBlue();
        return geversConverter.getColor(r, g, b);
    }


    public static HSVColor fromRGBtoHSV(RGBColor rgb) {
        int r = rgb.getRed();
        int g = rgb.getGreen();
        int b = rgb.getBlue();
        return hsvConverter.getColor(r, g, b);
    }

    public static interface ColorSpaceConverter<T> {
        public T getColor(int r, int g, int b);
    }

    public static class HSIColorSpaceConverter implements ColorSpaceConverter {
        public HSIColor getColor(int r, int g, int b) {
            // Initialise HSI values
            double hue = 0;
            double saturation = 0;
            double intensity;

            // Calculate maximum, and minimum of the RGB component values
            int max, min;
            if (r > g && r > b) {
                max = r;
                min = Math.min(g, b);
            } else {
                if (g > b) {
                    max = g;
                    min = Math.min(r, b);
                } else {
                    max = b;
                    min = Math.min(r, g);
                }
            }

            // Calculate intensity
            intensity = Math.round(((float) max / 255) * 100);
            if (intensity == 0) return new HSIColor(hue, saturation, intensity);

            // Calculate saturation
            if (max == min) return new HSIColor(hue, saturation, intensity);
            saturation = Math.round((((float) max / 255) - ((float) min / 255)) / ((float) max / 255) * 100);

            // Calculate hue
            double dbl_hue = Math.acos((0.5 * ((r - g) + (r - b))) / (Math.sqrt(Math.pow((r - g), 2) + (r - b) * (g - b))));
            if (b > g) dbl_hue = (2 * Math.PI) - dbl_hue;
            dbl_hue = Math.toDegrees(dbl_hue);
            hue = Math.round(Math.round(dbl_hue));

            return new HSIColor(hue, saturation, intensity);
        }
    }

    public static class HSVColorSpaceConverter implements ColorSpaceConverter<HSVColor> {
        public HSVColor getColor(int r, int g, int b) {
            return new HSVColor(java.awt.Color.RGBtoHSB(r, g, b, new float[3]));

        }
    }

    public static class GeversColorSpaceConverter implements ColorSpaceConverter<GeversColor> {
        public GeversColor getColor(int r, int g, int b) {
            double c1;
            double c2;
            double c3;
            c1 = Math.atan(r / Math.max(g, b));
            c2 = Math.atan(g / Math.max(r, b));
            c3 = Math.atan(b / Math.max(r, g));
            return new GeversColor(c1, c2, c3);

        }
    }
}
